.386
data segment use16
	;only fileLen and readLen are of dd type
	fileHandle dw 0;offset=0
	fileLen dd 0;offset=2
	hexLen dd 0;offset=6
	readLen dd 120;offset=A
	processedLen dd 0;offset=E
	remainedLen dd 0;offset=12
	_offset dd 0;offset=16
	bufLen dd 0;offset=1A
	
	;offset=1E
	fileName db 16, 0
			db 16 dup(0)
	;offset=30
	hexString db 100, 0
			db 100 dup(0)
	;offset=96
	hex db 100 dup(0)
	;offset=FA
	readFileBuffer db 120 dup(0)
	
	
	hintInputFileName db 'Input file name:', 0Dh, 0Ah, '$'
	hintInputHex db 'Input hex string:', 0Dh, 0Ah, '$'
	hintOpenErr db 'Open file failed!', 0Dh, 0Ah, '$'
	hintCloseErr db 'Close file failed!', 0Dh, 0Ah, '$'
	hintNotFound db "Not found!", 0Dh, 0Ah, '$'
	hintFound db "found at ", '$'
	


data ends
code segment use16
assume cs:code, ds:data
output_hint:
	mov ah, 09h
	int 21h
	ret
input_func:
	mov ah, 0Ah
	int 21h
	ret
get_file_len:
	;把指针移到文件结尾
	mov ah, 42h
	mov al, 2
	mov bx, fileHandle
	xor cx, cx
	xor dx, dx
	int 21h
	;返回DX|AX为文件长度
	;小端在前
	mov di, offset fileLen
	mov word ptr [di], ax;低8位 ;!!
	mov word ptr [di + 2], dx;高8位 ;!!
	;移回指针到文件开头
	mov ah, 42h
	mov al, 0
	mov bx, fileHandle
	xor cx, cx
	xor dx, dx
	int 21h
	ret
get_hex_len:
	;求十六进制串中包含的字节数
	xor ax, ax
	mov bp, offset hexString + 1
	mov al, ds:[bp];读入的字符数
	add ax, 1
	mov bl, 3
	div bl
	;AL中存储商,正常情况下AH,即余数必为0
	mov word ptr [hexLen], ax;!!
	ret
convert_hexstr2hex:
	mov al, ds:[di + offset hexString + 2]
	cmp al, 0Dh
	je convert_hexstr2hex_done
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	;if '0'<=al<='9'&&'A'<=al<='F'
	;    ^        ^    ^        ^
	;    48       57   65       70
	cmp al, ' '
	je convert_hexstr2hex_tail
	xor bx, bx
	cmp al, 'A'
	jnb AtoF1
	sub al, '0'
	mov cl, 4
	mov bl, al
	shl bl, 4
next_hex:
	inc di
	mov al, ds:[di + offset hexString + 2]
	cmp al, 'A'
	jnb AtoF2
	sub al, '0'
	add bl, al
	mov byte ptr [offset hex + si], bl
	inc si
	jmp convert_hexstr2hex_tail
AtoF1:
	sub al, 'A'
	add al, 10
	mov cl, 4
	mov bl, al
	shl bl, 4
	jmp next_hex
AtoF2:
	sub al, 'A'
	add al, 10
	add bl, al
	mov byte ptr [offset hex + si], bl
	inc si
	jmp convert_hexstr2hex_tail
convert_hexstr2hex_tail:
	inc di
	jmp convert_hexstr2hex
convert_hexstr2hex_done: 
	ret

main:
	mov ax, data
	mov ds, ax
	mov dx, offset hintInputFileName
	call output_hint
	mov dx, offset fileName
	call input_func
	call print_endl
	;修改fileName的最后一个回车字符为0
	mov si, offset fileName + 1
	xor ah, ah
	mov al, byte ptr [si]
	xor si, si
	mov si, ax
	add si, offset fileName + 2
	mov byte ptr [si], 0
	mov dx, offset hintInputHex
	call output_hint
	mov dx, offset hexString
	call input_func
	call print_endl
	mov dx, offset fileName + 2
	mov ah, 3Dh
	mov al, 0
	int 21h
	jnc open_success
open_fail:
	mov dx, offset hintOpenErr
	call output_hint
	jmp terminate
open_success:
	mov word ptr [fileHandle], ax ;!
	call get_file_len
	call get_hex_len
	;将hexString转化成hex
	xor si, si
	xor di, di
	call convert_hexstr2hex
search_hex:
	;while (fileLen!=0)
	mov ecx, [fileLen]
	cmp ecx, 0
	jne in_while_loop
not_found:
	mov dx, offset hintNotFound
	call output_hint
	jmp terminate
in_while_loop:
	;_offset+=processedLen
	mov ecx, [_offset];cx = _offset
	add ecx, [processedLen];cx => processedLen+_offset
	mov [_offset], ecx;_offset => _offset+processedLen
	;readLen=fileLen<readLen?fileLen:readLen;
	mov ecx, [fileLen];cx = fileLen
	xor edx, edx
	mov edx, [readLen];dx = readLen	
	cmp ecx, edx;if (fileLen<readLen)
	jb assign_read_len;readLen=fileLen
	jnb assign_read_len_back
assign_read_len:
	;readLen=fileLen
	mov edx, ecx
	mov [readLen], edx
assign_read_len_back:
	xor ax, ax
	mov ah, 3Fh
	mov bx, fileHandle
	mov cx, word ptr [readLen]
	mov dx, offset readFileBuffer
	add dx, word ptr [remainedLen]
	;mov dx, 0
	int 21h
	;fileLen=fileLen-readLen
	mov ecx, [fileLen]
	sub ecx, [readLen]
	mov [fileLen], ecx
	;bufLen=remainedLen+readLen
	mov ecx, [remainedLen]
	add ecx, [readLen]
	mov [bufLen], ecx
	;if (bufLen<hexLen)
	mov edx, [hexLen]
	cmp ecx, edx
	jb search_hex;continue
	;q=eax
	mov eax, offset readFileBuffer
scan:;while q <= buf+buf_len-hex_len
	;由于以下的变量实际上范围都在dw
	;所以可以把32寄存器的高16位忽略掉
	mov edx, offset readFileBuffer
	add edx, [bufLen]
	sub edx, [hexLen]
	cmp eax, edx
	;while(q<=buf+bufLen-hexLen)
	ja scan_break
	;ecx=distance=buf+buLen-hexLen-q+1
	mov ecx, offset readFileBuffer
	add ecx, [bufLen]
	sub ecx, [hexLen]
	sub ecx, eax
	inc ecx
	;search for hex[0]
	;保存q的值
	push eax
	mov dx, data
	mov es, dx
	mov di, ax
	mov al, hex[0]
	cld
	repne scasb;cx的次数设置存疑
	jne scan_break;p==NULL,break
	dec di
	pop eax
	push di
	mov si, offset hex
	mov cx, word ptr [hexLen]
	cld
	repe cmpsb
	je equal;此处存疑
	pop di
	;eax = di
	xor eax, eax
	mov ax, di
	inc eax
	jmp scan;continue
equal:
	pop di
	xor eax, eax
	mov ax, di
	mov ebx, [_offset]
	add ebx, eax
	sub ebx, offset readFileBuffer
	mov [_offset], ebx
	jmp found
scan_break:
	mov ecx, [bufLen]
	sub ecx, [hexLen]
	inc ecx
	mov [processedLen], ecx
	mov eax, offset readFileBuffer
	add eax, [processedLen]
	mov ecx, [hexLen]
	dec ecx
	mov [remainedLen], ecx

	;memcpy(buf, q, remainedLen)
	;...
	;"rep movsb"
	;rep~repeat s~string b~byte
	;preparing work:
	;	(1)es:di -> dest string
	;	(2)ds:si -> copy string
	;	(2)cx -> loop time
	;	(3)DF=0 -> positive direction
	;		using cmd "cld" clear direction
	;	   DF=1 -> negtivate direction
	;	    using cmd "std" set direction
	
	mov dx, data
	mov es, dx
	mov di, offset readFileBuffer
	mov si, ax
	mov cx, word ptr [remainedLen]
	cld
	rep movsb
	
	mov ecx, 120;sizeof(buffer)
	sub ecx, [remainedLen]
	mov [readLen], ecx
	jmp search_hex
found:
	mov dx, offset hintFound
	mov ah, 09h
	int 21h
	call output_hex
	jmp terminate
close_fail:
	mov dx, offset hintCloseErr
	mov ah, 09h
	int 21h
	jmp terminate
terminate:
	mov ah, 4Ch
	int 21h
print_enter:
	push ax
	push dx
	mov ah, 02h
	mov dl, 0Dh
	int 21h
	pop dx
	pop ax
	ret
print_endl:
	push ax
	push dx
	mov ah, 02h
	mov dl, 0Ah
	int 21h
	pop dx
	pop ax
	ret


;function: output_hex - output hex number
;use: ansh = high 16bit, ansl = low16bit, it will print on
;     the screen.	
	output_hex:
		mov si, offset _offset
		mov dx, 0
		mov ax, ds:[si+2]
;output ansh in hex
		call output_hex_loop
		mov si, offset _offset
		mov dx, 0
		mov ax, ds:[si]
;output ansl in hex
		call output_hex_loop
;print 'h'
		mov ah, 02h
		mov dl, 0Dh
		int 21h
		mov dl, 0Ah
		int 21h
		ret
;output_hex_loop is used to print a 16bit number in hex format
;use: ax=16bit value, dx=0
	output_hex_loop:
		cmp dx, 4
		je output_hex_loop_done
		inc dx
;evert loop shift left 4bits(0~F) to get next hex digit
		rol ax, 4
;push ax and protect it
		push ax
		and ax, 000Fh
		cmp ax, 10
;if ax is bigger than 10, we need to print 'A'to'F'
		jnb over_than10
		add ax, '0'
;output ax
		jmp output_hex4bit
;return:end of function
		output_hex_loop_done: ret
	over_than10:
		sub ax, 10
		add ax, 'A'
	output_hex4bit:
		push dx
		mov dl, al
		mov ah, 02h
		int 21h
		pop dx
		pop ax
		jmp output_hex_loop
		
code ends
end main